<?php

namespace pmvc\data\sql\sqlite3;

use pmvc\data\sql\AbstractDataSource;
use pmvc\util\StringUtil;
use Exception;
use SQLite3;

class SQLite3DataSource 
	extends AbstractDataSource {

	public $filename;
	public $flags;
	public $encryptionKey = null;
	
	private $sqlite3 = false;

	public function createTransaction() {
		return new SQLite3Transaction($this);
	}

	public function connect() {
		if ($this->sqlite3!==false) {
			return;
		}
		if (empty($this->filename)) {
			throw new Exception("Database filename not specified");
		}
		if (empty($this->flags)) {
			$this->flags = SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE;
		}
		$this->sqlite3 = new SQLite3($this->filename, $this->flags, $this->encryptionKey);
	
		$this->assert($this->sqlite3!==false, "Opening database failed");
	}
	
	public function escape($str) {
		return $this->sqlite3->escapeString($str);
	}
	
	public function query() {
		$a		= func_get_args();
        $sql 	= array_shift($a);
        $sql 	= $this->buildQuery($sql, $a);
        \pmvc\log\Log::trace(__CLASS__, "Executing query: {0}", $sql);
        $ret = $this->sqlite3->query($sql);
        $this->assert($ret!==false, "Query failed");
        return $ret;
	}
	
	public function update() {
		return call_user_func_array(array($this,"query"), func_get_args());
	}
	
	public function lastInsertId() {
		$ret = $this->sqlite3->lastInsertRowID();
		$this->assert($ret!==false, "Getting insert id failed");
        return $ret;
	}
	
	public function numberOfRows($res) {
		return -1;
	}
	
	public function fetchRowObject($res) {
		$ret = $res->fetchArray(SQLITE3_ASSOC);
		return $ret!==false ? (object)$ret : false;
	}
	
	public function numberOfAffectedRows($res) {
		return -1;
	}
	
	public function freeResult($res) {
		return $res->finalize();
	}

	public function getLastError() {
		$lastError = $this->sqlite3->lastErrorCode();
		$message = $this->sqlite3->lastErrorMsg();
		return "errno ".$lastError." - ".$message;
	}

	private function assert($value, $message="") {
		if ($value!==true) {
			throw $this->createExceptionFromLastError($message);
		}
	}

	private function createExceptionFromLastError($message="", $previous=null) {
		$lastError = $this->sqlite3->lastErrorCode();
		$message = $this->sqlite3->lastErrorMsg();
		return new Exception($message." - ".$message, $lastError, $previous);
	}

}

?>